import re

import datetime as dt

import numpy as np

from matplotlib.dates import date2num

from metrics import pls

import utilsabbo as util
import get_data

def set_up(data_tab, pls_order, para_set, stop_day=dt.datetime(2011,01,01),
            over_filter=None, length_of_model_period=200, pred_days=20):
    """
    This uses a number of samples instead of a number days to generated the model
    This ensures that a model will be generated but the data used for the generation can be old
    """
    if not over_filter:
        over_filter = ["(ActivePowerAvg >= 200)", "(ActivePowerAvg < 2200)"]
    xdata = []
    xval = []

    length_of_model_period = length_of_model_period/2

    filt = over_filter + ["(Time < " + str(date2num(stop_day)) + ")"]
    filt_cross = over_filter + ["(Time >= " + str(date2num(stop_day)) + ")",
            "(Time < " + str(date2num(stop_day + dt.timedelta(days=pred_days))) + ")"]

    xdat = get_data.filter_h5data(data_tab, filt, startnum=0, steplen=2)
    xdat = xdat[-length_of_model_period:]

    xvaldat = get_data.filter_h5data(data_tab, filt, startnum=1, steplen=2)
    xvaldat = xvaldat[-length_of_model_period:]

    xcrossdat = get_data.filter_h5data(data_tab, filt_cross, startnum=0, steplen=1)

    model_data = [xdat, xvaldat, xcrossdat]

    x_parameters = para_set['x_para']
    y_parameters = para_set['y_para']

    xdata = util.get_specific_data(model_data[0], x_parameters)
    xval = util.get_specific_data(model_data[1], x_parameters)
    xcross = util.get_specific_data(model_data[2], x_parameters)
    ydata = util.get_specific_data(model_data[0], y_parameters)
    yval = util.get_specific_data(model_data[1], y_parameters)
    ycross = util.get_specific_data(model_data[2], y_parameters)

    mskdata = np.zeros((len(xdata), 1))
    mskval = np.ones((len(xval), 1))
    mskcross = 2*np.ones((len(xcross),1))
    msk = np.vstack((mskdata, mskval, mskcross))
    xmodel = np.vstack((xdata, xval, xcross))
    ymodel = np.vstack((ydata, yval, ycross))
    pls_out = pls(xmodel, ymodel, msk, pls_order)
    xmodel = np.vstack((xdata, xval))
    ymodel = np.vstack((ydata, yval))
    pls_out['xmean'] = np.mean(xmodel, axis=0)
    pls_out['ymean'] = np.mean(ymodel, axis=0)
    return pls_out

def set_up2(data_tab, pls_order, para_set, stop_day=dt.datetime(2011,01,01),
            over_filter=None, length_of_model_period=200, pred_days=20):
    """
    This uses a number of samples instead of a number days to generated the model
    This ensures that a model will be generated but the data used for the generation can be old
    """
    if not over_filter:
        over_filter = ["(ActivePowerAvg >= 200)", "(ActivePowerAvg < 2200)"]
    xdata = []
    xval = []

    length_of_model_period = length_of_model_period/2

    filt = over_filter + ["(Time < " + str(date2num(stop_day)) + ")"]

    xdat = get_data.filter_h5data(data_tab, filt, startnum=0, steplen=2)
    xdat = xdat[-length_of_model_period:]

    xvaldat = get_data.filter_h5data(data_tab, filt, startnum=1, steplen=2)
    xvaldat = xvaldat[-length_of_model_period:]

    model_data = [xdat, xvaldat]

    x_parameters = para_set['x_para']
    y_parameters = para_set['y_para']

    xdata = util.get_specific_data(model_data[0], x_parameters)
    xval = util.get_specific_data(model_data[1], x_parameters)
    ydata = util.get_specific_data(model_data[0], y_parameters)
    yval = util.get_specific_data(model_data[1], y_parameters)

    mskdata = np.zeros((len(xdata), 1))
    mskval = np.ones((len(xval), 1))
    msk = np.vstack((mskdata, mskval))
    xmodel = np.vstack((xdata, xval))
    ymodel = np.vstack((ydata, yval))
    pls_out = pls(xmodel, ymodel, msk, pls_order)
    xmodel = np.vstack((xdata, xval))
    ymodel = np.vstack((ydata, yval))
    pls_out['xmean'] = np.mean(xmodel, axis=0)
    pls_out['ymean'] = np.mean(ymodel, axis=0)
    return pls_out

def get_temp_set(key_list, y_para):
    """ Construct different combination of parameters to be used for fault detection
    """
    temp_keys = []
    for key in sorted(key_list):
        match = re.search(r"(.*Temp)?", key)
        if match:
            if match.group(1):
                temp_keys.append(key)

    para_sets = []
    para_set = {}
    para_set['y_para'] = [y_para,]
    spam = []
    for temp_key in temp_keys:
        if temp_key != para_set['y_para'][0]:
            spam.append(temp_key)

    para_set['x_para'] = spam
    para_set['x_para'] = tuple(['GearOilTempAvg', 'GeneratorBearTempAvg', 'HydraulicOilTempAvg', 'NacelleTempAvg'])
    para_sets.append(para_set)
    return para_sets

def get_temp_keys(key_list):
    """ Construct different combination of parameters to be used for fault detection
    """
    temp_keys = []
    for key in sorted(key_list):
        match = re.search(r"(.*Temp)?", key)
        if match:
            if match.group(1):
                temp_keys.append(key)
    return temp_keys

def predict( x, b, x_mean, y_mean):
    return y_mean + np.dot(x, b.T) - np.dot(x_mean, b.T)
